{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from pprint import pprint as pp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "a = np.arange(32).reshape(4,8)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 通用的分割函数 np.split\n",
    "#### np.split(a, 2, axis=0)  # 相当于np.vsplit)\n",
    "#### np.split(a, 2, axis=1)  # 相当于np.hsplit)\n",
    "#### np.split(a, 2, axis=2)  # 相当于np.dsplit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 把阵列按垂直方向切分，垂直方向就是 axis=0，也就是第一个轴\n",
    "# 相当于 np.split(a, axis=0)\n",
    "pp(np.vsplit(a, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 明确地指定分割点\n",
    "# [1,3] 相当于 a[:1], a[1:3], a[3:]\n",
    "pp(np.vsplit(a, [1,3]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 相当于 np.split(a, axis=1)\n",
    "pp(np.hsplit(a,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可以用负数来指定分割点\n",
    "pp(np.hsplit(a, [1,4,7,-1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 准备一个3维数组\n",
    "a = np.arange(96).reshape(4,3,8)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pp(np.dsplit(a,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.split(a, [3,5], axis=2)\n",
    "pp(np.dsplit(a,[3,5]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.split 可以应用于超过3个轴的阵列，不过vplit, hsplit, dsplit是便利函数，最多只能操作到第3轴。\n",
    "a = np.arange(32).reshape(2,2,2,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.dsplit 仍然能够处理轴数超过3的阵列，只不过不能操作第4及以上的轴。\n",
    "# 如果需要操作第4及以上的轴，可以使用通用的 np.split\n",
    "pp(np.dsplit(a,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可以看出，最高轴（3轴）已经被切开\n",
    "pp(np.split(a, 2, axis=3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 近似平均地切分阵列\n",
    "a = np.arange(10)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# np.split(a, 3)   # 本语句会出错\n",
    "pp(np.array_split(a, 3))\n",
    "pp(np.array_split(a, 4))\n",
    "pp(np.array_split(a, 9))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 阵列的副本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(12)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a 和 b 都是阵列， b 是浅副本，共用别的阵列的数据\n",
    "b = a.view()\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a.flags.owndata, b.flags.owndata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 共用同一份数据的多个阵列，形状可以不同\n",
    "# b.shape\n",
    "b.shape = (3,4)\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b.base is a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b.shape, a.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 定义一个简单的便利函数，用来判断阵列是不是视图\n",
    "def isview(a):\n",
    "    return a.base is not None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对阵列做切片操作，所生成的阵列是元阵列的视图\n",
    "c = a[-2:]\n",
    "isview(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c.size, a.size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "large_a = np.arange(10000)\n",
    "%timeit large_a.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%timeit large_a.view()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 改变a的形状\n",
    "a.shape = (3,4)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "isview(a.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a.flags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在无法重用旧数据时，numpy会复制一份数据，这时候ravel生成了深副本\n",
    "isview(a.ravel(order='F'))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
